package com.lry.netty01.server.in;

import com.lry.netty01.server.Server;
import com.lry.netty01.server.entity.FixedFrame;
import com.lry.netty01.server.entity.Packet;
import com.lry.netty01.server.queue.Task;
import com.lry.netty01.server.utils.ChannelUtil;
import com.lry.netty01.server.utils.CommandUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

    }



    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
                                Throwable cause) {
        short devId =  ChannelUtil.online_channels.get(ctx.channel());
        log.info(devId+" netty捕获到异常:"+cause);
    }

    //设备下线
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        short devId =  ChannelUtil.online_channels.get(ctx.channel());
        ChannelUtil.clearCache(devId,ctx.channel());
    }

    /**
     * 30s服务端没有发送任何数据给客户端，发一个心跳
     * @param ctx
     */
    protected void handlerWriterIdle(ChannelHandlerContext ctx) {
        Short devId = ChannelUtil.online_channels.get(ctx.channel());
        if(devId!=null){
            Packet packet = new Packet(false,ctx.channel(),new FixedFrame(CommandUtil.HEART_BEAT_CMD,devId,(byte)0));
            //发送心跳
            Server.offerTaskQueue(new Task(packet));
        }
    }

    /**
     * 1min 服务端没有收到客户端任何数据，踢掉，下线
     * @param ctx
     */
    protected void handlerReaderIdle(ChannelHandlerContext ctx) {
        short devId =  ChannelUtil.online_channels.get(ctx.channel());
        ChannelUtil.clearCache(devId,ctx.channel());
    }

    protected void handlerAllIdle(ChannelHandlerContext ctx) {
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
            throws Exception {
        IdleStateEvent stateEvent = (IdleStateEvent) evt;

        switch (stateEvent.state()) {
            case READER_IDLE:
                handlerReaderIdle(ctx);
                break;
            case WRITER_IDLE:
                handlerWriterIdle(ctx);
                break;
            case ALL_IDLE:
                handlerAllIdle(ctx);
                break;
            default:
                break;
        }
    }

}
